package com.example.hxds.dr.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.example.hxds.common.exception.HxdsException;
import com.example.hxds.common.util.MicroAppUtil;
import com.example.hxds.common.util.PageUtils;
import com.example.hxds.dr.db.dao.DriverDao;
import com.example.hxds.dr.db.dao.DriverSettingsDao;
import com.example.hxds.dr.db.dao.WalletDao;
import com.example.hxds.dr.db.pojo.DriverSettingsEntity;
import com.example.hxds.dr.db.pojo.WalletEntity;
import com.example.hxds.dr.service.DriverService;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.iai.v20200303.IaiClient;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonRequest;
import com.tencentcloudapi.iai.v20200303.models.CreatePersonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: DriverServiceImpl
 * @Description: 司机类服务层实现类
 * @Author: 丛雨
 * @Date: 2024/1/13 17:12
 */
@Service
@Slf4j
public class DriverServiceImpl implements DriverService {
    @Resource
    private MicroAppUtil microAppUtil;

    @Resource
    private DriverDao driverDao;

    @Resource
    private DriverSettingsDao driverSettingsDao;

    @Resource
    private WalletDao walletDao;

    @Value("${tencent.cloud.secretId}")
    private String secretId;

    @Value("${tencent.cloud.secretKey}")
    private String secretKey;

    @Value("${tencent.face.groupName}")
    private String groupName;

    @Value("${tencent.face.region}")
    private String region;

    /**
     * 注册新司机用户
     *
     * @param param 前端传入参数
     * @return 返回司机ID
     */
    @Override
    @Transactional
    @LcnTransaction
    public String registerNewDriver(Map param) {
        // 1. 新司机注册
        // 从传入的Map获取短期授权码
        String code = MapUtil.getStr(param, "code");
        // 利用微信工具类将短期授权码转换为长期授权码
        String openId = microAppUtil.getOpenId(code);
        // 将长期授权码存储到HashMap中
        HashMap tempParam = new HashMap<>() {{
            put("openId", openId);
        }};
        // 通过长期授权码验证司机是否已经注册
        if (driverDao.hasDriver(tempParam) != 0) {
            throw new HxdsException("该微信无法注册");
        }
        param.put("openId", openId);
        driverDao.registerNewDriver(param);
        // 通过长期授权码获取司机Id,前端无法识别long,需要在mapper层转换为String
        String driverId = driverDao.searchDriverId(openId);

        // 2. 添加司机设置记录
        DriverSettingsEntity driverSettingsEntity = new DriverSettingsEntity();
        // 再次将String转换为long
        driverSettingsEntity.setDriverId(Long.parseLong(driverId));
        JSONObject json = new JSONObject();
        json.set("autoAccept", false); // 自动抢单
        json.set("orientation", ""); // 定向接单
        json.set("listenService", true); // 自动听单
        json.set("orderDistance", 0); // 代驾订单预估里程不限,司机不挑订单
        json.set("rangeDistance", 5); // 接收距离司机5公里以内的代驾单
        driverSettingsEntity.setSettings(json.toString());
        driverSettingsDao.insertDriverSettings(driverSettingsEntity);

        // 3. 添加司机钱包记录
        WalletEntity walletEntity = new WalletEntity();
        walletEntity.setDriverId(Long.parseLong(driverId));
        walletEntity.setBalance(new BigDecimal(0));
        walletEntity.setPassword(null);
        walletDao.insert(walletEntity);
        return driverId;
    }

    /**
     * 司机实名认证
     *
     * @param param 司机信息
     * @return 执行SQL后返回的行数
     */
    @Override
    @Transactional
    @LcnTransaction
    public int updateDriverAuth(Map param) {
        int rows = driverDao.updateDriverAuth(param);
        return rows;
    }

    /**
     * 创建司机人脸模型归档
     *
     * @param driverId 司机Id
     * @param photo    司机面部照片Base64字符串
     * @return 归档结果
     */
    @Override
    @Transactional
    @LcnTransaction
    public String createDriverFaceModel(long driverId, String photo) {
        HashMap map = driverDao.searchDriverNameAndSex(driverId);
        String name = MapUtil.getStr(map, "name");
        String sex = MapUtil.getStr(map, "sex");
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            Credential cred = new Credential(secretId, secretKey);
            // 实例化要请求产品的client对象
            IaiClient client = new IaiClient(cred, region);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            CreatePersonRequest req = new CreatePersonRequest();
            // 将需要上传的参数逐个填写
            req.setGroupId(groupName);
            req.setPersonName(name);
            req.setPersonId(driverId + "");
            long gender = sex.equals("男") ? 1L : 2L;
            req.setGender(gender);
            req.setImage(photo);
            req.setUniquePersonControl(4L);
            req.setQualityControl(4L);
            // 返回的resp是一个CreatePersonResponse的实例，与请求对象对应
            CreatePersonResponse resp = client.CreatePerson(req);
            // 输出json格式的字符串回包
            System.out.println(CreatePersonResponse.toJsonString(resp));
            // 如果成功上传,那么就修改司机的'档案'属性
            if (!StrUtil.isBlank(resp.getFaceId())) {
                int rows = driverDao.updateDriverArchive(driverId);
                if (rows != 1) {
                    return "更新司机归档字段失败";
                }
            }
        } catch (TencentCloudSDKException e) {
            log.error("创建腾讯云端司机档案失败", e);
            return "创建腾讯云端司机档案失败";
        }
        return "";
    }

    /**
     * 司机登录
     *
     * @param code 微信小程序临时授权码
     * @return 登陆结果
     */
    @Override
    public HashMap login(String code) {
        String openId = microAppUtil.getOpenId(code);
        HashMap result = driverDao.login(openId);
        if (result != null && result.containsKey("archive")) {
            Integer temp = MapUtil.getInt(result, "archive");
            boolean archive = (temp == 1) ? true : false;
            result.replace("archive", archive);
        }
        return result;
    }

    /**
     * 查询司机基本信息
     *
     * @param driverId 司机Id
     * @return 查询结果
     */
    @Override
    public HashMap searchDriverBaseInfo(long driverId) {
        HashMap result = driverDao.searchDriverBaseInfo(driverId);
        JSONObject summary = JSONUtil.parseObj(MapUtil.getStr(result, "summary"));
        result.replace("summary", summary);
        return result;
    }

    /**
     * 查询司机认证状态
     *
     * @param driverId 司机Id
     * @return 查询结果
     */
    @Override
    public byte searchDriverRealAuth(long driverId) {
        byte realAuth = driverDao.searchDriverRealAuth(driverId);
        return realAuth;
    }

    /**
     * 查询司机分页数据
     *
     * @param param 查询条件
     * @return 查询结果
     */
    @Override
    public PageUtils searchDriverByPage(Map param) {
        // 先查询数据库是否存在数据
        long count = driverDao.searchDriverCount(param);
        ArrayList<HashMap> list = null;
        if (count == 0) {
            list = new ArrayList<>();
        } else {
            list = driverDao.searchDriverByPage(param);
        }
        Integer start = (Integer) param.get("start");
        Integer length = (Integer) param.get("length");
        // list:数据列表,count:总记录数,start:当前页数(行数),length:每页记录数
        PageUtils pageUtils = new PageUtils(list, count, start, length);
        return pageUtils;
    }

    /**
     * 查询司机实名认证信息
     *
     * @param driverId 司机Id
     * @return 查询结果
     */
    @Override
    public HashMap searchDriverAuth(long driverId) {
        HashMap result = driverDao.searchDriverAuth(driverId);
        return result;
    }

    /**
     * 查询司机实名信息摘要
     *
     * @param driverId 司机Id
     * @return 查询结果
     */
    @Override
    public HashMap searchDriverRealSummary(long driverId) {
        HashMap result = driverDao.searchDriverRealSummary(driverId);
        return result;
    }

    /**
     * 更新司机实名认证状态
     *
     * @param param 包含司机Id和认证状态
     * @return 更新结果
     */
    @Override
    @Transactional
    @LcnTransaction
    public int updateDriverRealAuth(Map param) {
        int rows = driverDao.updateDriverRealAuth(param);
        return rows;
    }
}
